package primitives;

import java.util.ArrayList;
import java.util.Iterator;

import light.Light;
import colour.Colour;
import ray.Ray;
import shadow.ShadowsCalculation;
import surface.Surface;
import vector.Vector;

/**
 * This class is used for presenting all the shapes.
 * 
 * @author Yuting Wu
 * @author Kan Lin
 * 
 */
public abstract class AbstractShape {
	protected Surface surface;

	public AbstractShape(Surface surface) {
		this.surface = surface;
	}

	// calculate the surface color for the hitpoint
	public abstract Colour getColorAt(Vector pHitPoint, Vector vHitPoint);

	// return the diffuse value in the surface
	public abstract double getDiffuse();

	// return the Reflect value in the surface
	public abstract double getReflect();

	// hit calcuation check whether hit or not
	public abstract boolean calMutiIntersection(Ray raylist, Boolean ifSimple);

	// do the hitpoint position and normal vector calcaulation after hit is
	// known
	public abstract void runFurtherCalculation(final Ray rayInput);

	// calculation the hitpoint
	public abstract Vector getVectorHitPointIndex();

	// calculation the position of the hitpoint
	public abstract Vector getPositionHitPointIndex();

	// get the distance from the hitpoint to origin of the ray
	public abstract double getDisHitPointIndex();

	public abstract boolean isInsideOrOutside();

	// Calculate the angle of the light and hit vector and intensity
	public abstract double lightIntensityCalculation(Light singleLight,
			Vector pHitPoint, Vector vHitPoint);

	/**
	 * Calculate the angle value for muti light
	 * 
	 * 
	 * @param ifshadow
	 *            used for open shadow calculation
	 * 
	 * @return the angleValue
	 */
	public double multiLightIntensityCalculation(World3D world,
			Vector pHitPoint, Vector vHitPoint, boolean ifshadow) {

		//get the array of light from the world
		ArrayList<Light> light = world.getLight();
		
		Iterator<Light> itl = light.iterator();
		double angleValue = 0.0;
		
		ShadowsCalculation sc = new ShadowsCalculation(pHitPoint, world);
		while (itl.hasNext()) {
			Light singleLight = itl.next();
			angleValue = angleValue
					+ sc.shadowJudge(singleLight, ifshadow)
					* this.lightIntensityCalculation(singleLight, pHitPoint,
							vHitPoint);
		}
		return angleValue;

	}

}
